package scaladuct.l10n

import java.util.Locale
import scaladuct.Property
import java.net.URL
import java.lang.String

/**
 * <p>
 * Created by IntelliJ IDEA.
 * User: zslajchrt
 * Date: Dec 13, 2010
 * Time: 12:26:10 PM
 */

trait ConfigPageMetaData {
  def pageLocale: Locale

  def pageMeta: Option[CommonMetaData]

  def propertyMeta[X](property: Property[X]): Option[CommonMetaData]

  def propertyValueMeta[X](property: Property[X]): Option[CommonMetaData]
}

trait CommonMetaData {
  def title: Option[String]

  def description: Option[String]

  def icon: Option[URL]
}

class DefaultCommonMetaData(val title: Option[String], val description: Option[String], val icon: Option[URL]) extends CommonMetaData

@serializable @SerialVersionUID(1L)
trait ConfigPageMetaDataSource {
  def configPageMetaData(locale: Locale): Option[ConfigPageMetaData]
}

@serializable @SerialVersionUID(1L)
trait ConfigPageMetaDataSourceProvider {
  def configPageMetaDataSource(phaseMethod: String): Option[ConfigPageMetaDataSource]
}

trait ConfigPageMetaDataSourceWrapper extends ConfigPageMetaDataSource {
  val wrappedConfigPageMetaDataSource: ConfigPageMetaDataSource

  def configPageMetaData(locale: Locale) = wrappedConfigPageMetaDataSource.configPageMetaData(locale)
}

trait DuplexHasHintsMetaDataSource extends HasHintsMetaDataSource {
  val firstConfigPageMetaDataSource: HasHintsMetaDataSource
  val secondConfigPageMetaDataSource: HasHintsMetaDataSource

  def configPageMetaData(locale: Locale) = {
    firstConfigPageMetaDataSource.configPageMetaData(locale) match {
      case Some(firstMetaData) => {
        secondConfigPageMetaDataSource.configPageMetaData(locale) match {
          case Some(secondMetaData) => {
            Some(new DuplexHasHintsMetaData(locale, firstMetaData, secondMetaData))
          }
          case None => Some(firstMetaData)
        }
      }
      case None => secondConfigPageMetaDataSource.configPageMetaData(locale)
    }
  }
}

class DuplexHasHintsMetaData(val pageLocale: Locale,
                             firstConfigPageMetaData: HasHintsMetaData,
                             secondConfigPageMetaData: HasHintsMetaData)
        extends HasHintsMetaData {
  def retrieveMetaData(firstMetaDataRetriever: => Option[CommonMetaData],
                       secondMetaDataRetriever: => Option[CommonMetaData]): Option[CommonMetaData] = {

    firstMetaDataRetriever match {
      case Some(firstPageMeta) => {
        secondMetaDataRetriever match {
          case Some(secondPageMeta) => Some(new DuplexCommonMetaData(firstPageMeta, secondPageMeta))
          case None => Some(firstPageMeta)
        }
      }
      case None => secondMetaDataRetriever
    }
  }

  lazy val pageMeta = retrieveMetaData(firstConfigPageMetaData.pageMeta, secondConfigPageMetaData.pageMeta)

  def propertyMeta[X](property: Property[X]) = retrieveMetaData(
    firstConfigPageMetaData.propertyMeta(property),
    secondConfigPageMetaData.propertyMeta(property))

  def propertyValueMeta[X](property: Property[X]) = retrieveMetaData(
    firstConfigPageMetaData.propertyValueMeta(property),
    secondConfigPageMetaData.propertyValueMeta(property))

  def hintMeta[H](hint: Property[H]) = retrieveMetaData(
    firstConfigPageMetaData.hintMeta(hint),
    secondConfigPageMetaData.hintMeta(hint))


  class DuplexCommonMetaData(firstMetaData: CommonMetaData, secondMetaData: CommonMetaData) extends CommonMetaData {
    def retrieveValue[X](firstRetriever: => Option[X], secondRetriever: => Option[X]): Option[X] = {
      firstRetriever match {
        case Some(v1) => Some(v1)
        case None => secondRetriever
      }
    }

    def icon = retrieveValue(firstMetaData.icon, secondMetaData.icon)

    def description = retrieveValue(firstMetaData.description, secondMetaData.description)

    def title = retrieveValue(firstMetaData.title, secondMetaData.title)
  }
}
